// JavaScript language adapter implementation
use codegraph_core::{
    LanguageAdapter, Parser, SyntaxTree, CodeNode, CodeEdge, NodeType, Result,
    SourceLocation,
};
use codegraph_parser::TreeSitterParser;
use codegraph_graph::GraphNode;
use async_trait::async_trait;
use uuid::Uuid;


pub struct JavaScriptAdapter {
    language_id: String,
    file_extensions: Vec<String>,
}

impl JavaScriptAdapter {
    pub fn new() -> Self {
        Self {
            language_id: "javascript".to_string(),
            file_extensions: vec![".js".to_string(), ".mjs".to_string(), ".jsx".to_string()],
        }
    }
}

impl Default for JavaScriptAdapter {
    fn default() -> Self {
        Self::new()
    }
}

#[async_trait]
impl LanguageAdapter for JavaScriptAdapter {
    fn language_id(&self) -> &str {
        &self.language_id
    }

    fn file_extensions(&self) -> &[String] {
        &self.file_extensions
    }

    async fn create_parser(&self) -> Result<Box<dyn Parser>> {
        let parser = TreeSitterParser::javascript()?;
        Ok(Box::new(parser))
    }

    async fn extract_nodes(&self, tree: &dyn SyntaxTree) -> Result<Vec<Box<dyn CodeNode>>> {
        let mut nodes = Vec::new();

        // Extract function declarations
        self.extract_function_declarations(tree, &mut nodes).await?;

        Ok(nodes)
    }

    async fn extract_edges(&self, _tree: &dyn SyntaxTree, _nodes: &[&dyn CodeNode]) -> Result<Vec<Box<dyn CodeEdge>>> {
        // TODO: Implement edge extraction
        Ok(Vec::new())
    }

    fn map_syntax_type_to_node_type(&self, syntax_type: &str) -> NodeType {
        match syntax_type {
            "function_declaration" | "arrow_function" | "function_expression" => NodeType::Function,
            "class_declaration" => NodeType::Class,
            "variable_declaration" | "lexical_declaration" => NodeType::Variable,
            "import_statement" | "export_statement" => NodeType::Import,
            "call_expression" => NodeType::Call,
            "identifier" => NodeType::Reference,
            _ => NodeType::Unknown,
        }
    }
}

impl JavaScriptAdapter {
    async fn extract_function_declarations(
        &self,
        tree: &dyn SyntaxTree,
        nodes: &mut Vec<Box<dyn CodeNode>>,
    ) -> Result<()> {
        // Use Tree-sitter query to find function declarations
        let query_str = r#"
            (function_declaration
                name: (identifier) @func_name
                parameters: (formal_parameters) @params
                body: (statement_block) @body) @function
        "#;

        if let Ok(parser) = TreeSitterParser::javascript() {
            if let Ok(matches) = parser.query(query_str, tree) {
                for query_match in matches {
                    if let Some(func_node) = query_match.captures.get("func_name") {
                        let func_name = func_node.text().trim();
                        let start_pos = func_node.start_position();
                        let end_pos = func_node.end_position();

                        let node = GraphNode::new(
                            Uuid::new_v4(),
                            NodeType::Function,
                            func_name.to_string(),
                            SourceLocation::new(
                                "javascript_file.js".to_string(), // TODO: Get actual file path
                                start_pos.row,
                                start_pos.column,
                                end_pos.row,
                                end_pos.column,
                            ),
                            "javascript".to_string(),
                        );
                        nodes.push(Box::new(node));
                    }
                }
            }
        }

        Ok(())
    }
}
